/* Copyright Statement:
*
* This software/firmware and related documentation ("MediaTek Software") are
* protected under relevant copyright laws. The information contained herein
* is confidential and proprietary to MediaTek Inc. and/or its licensors.
* Without the prior written permission of MediaTek inc. and/or its licensors,
* any reproduction, modification, use or disclosure of MediaTek Software,
* and information contained herein, in whole or in part, shall be strictly prohibited.
*/
/* MediaTek Inc. (C) 2015. All rights reserved.
*
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
* THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
* CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
* SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
* CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*/

#ifndef _MSDC_DMA_H_
#define _MSDC_DMA_H_

#include "mmc_core.h"


/*--------------------------------------------------------------------------*/
/* DMA Related Define                                                     */
/*--------------------------------------------------------------------------*/
#if defined(MMC_MSDC_DRV_CTP)
#define MAX_GPD_POOL_SZ     (512)
#define MAX_BD_POOL_SZ      (1024)
#else
#define MAX_GPD_POOL_SZ     (2) /* include null gpd */
#define MAX_BD_POOL_SZ      (4)
#endif

#define MAX_DMA_CNT     (8*1024*1024)
#define MAX_SG_POOL_SZ      (MAX_BD_POOL_SZ)
#define MAX_SG_BUF_SZ       (MAX_DMA_CNT)
#define MAX_BD_PER_GPD      (MAX_BD_POOL_SZ) /* only one gpd for all bd */

#define MAX_DMA_TRAN_SIZE   ((u64)MAX_SG_POOL_SZ*MAX_SG_BUF_SZ)

#if MAX_SG_BUF_SZ > MAX_DMA_CNT
#error "incorrect max sg buffer size"
#endif


/*--------------------------------------------------------------------------*/
/* Descriptor Structure                                                     */
/*--------------------------------------------------------------------------*/
typedef struct {
	uint32  hwo:1; /* could be changed by hw */
	uint32  bdp:1;
	uint32  rsv0:6;
	uint32  chksum:8;
	uint32  intr:1;
	uint32  rsv1:7;
	uint32  nexth4:4;
	uint32  ptrh4:4;
	void   *next;
	void   *ptr;
	uint32  buflen:24;
	uint32  extlen:8;
	uint32  arg;
	uint32  blknum;
	uint32  cmd;
} gpd_t;

typedef struct {
	uint32  eol:1;
	uint32  rsv0:7;
	uint32  chksum:8;
	uint32  rsv1:1;
	uint32  blkpad:1;
	uint32  dwpad:1;
	uint32  rsv2:5;
	uint32  nexth4:4;
	uint32  ptrh4:4;
	void   *next;
	void   *ptr;
	uint32  buflen:24;
	uint32  rsv3:8;
} bd_t;

struct scatterlist {
	u32 addr;
	u32 len;
};

struct scatterlist_ex {
	u32 cmd;
	u32 arg;
	u32 sglen;
	struct scatterlist *sg;
};

struct dma_config {
	u32 flags;           /* flags */
	u64 xfersz;          /* xfer size in bytes */
	u32 sglen;           /* size of scatter list */
	u32 blklen;          /* block size */
	struct scatterlist *sg;  /* I/O scatter list */
	struct scatterlist_ex *esg;  /* extended I/O scatter list */
	u8  mode;            /* dma mode        */
	u8  burstsz;         /* burst size      */
	u8  intr;            /* dma done interrupt */
	u8  padding;         /* padding */
	u32 cmd;             /* enhanced mode command */
	u32 arg;             /* enhanced mode arg */
	u32 rsp;             /* enhanced mode command response */
	u32 autorsp;         /* auto command response */
	u8  inboot;          /* this flag is for Basic DMA in eMMC boot mode*/
};


void msdc_init_gpd_bd(struct mmc_host *host);
void msdc_flush_membuf(void *buf, u32 len);
u8 msdc_cal_checksum(u8 *buf, u32 len);
gpd_t *msdc_alloc_gpd(struct mmc_host *host, int num);
bd_t *msdc_alloc_bd(struct mmc_host *host, int num);
void msdc_queue_bd(struct mmc_host *host, gpd_t *gpd, bd_t *bd);
void msdc_queue_buf(struct mmc_host *host, gpd_t *gpd, u8 *buf);
void msdc_add_gpd(struct mmc_host *host, gpd_t *gpd, int num);
void msdc_reset_gpd(struct mmc_host *host);
void msdc_set_dma(struct mmc_host *host, u8 burstsz, u32 flags);
int msdc_sg_init(struct scatterlist *sg, void *buf, u64 buflen);
void msdc_dma_init(struct mmc_host *host, struct dma_config *cfg, void *buf, u64 buflen);
int msdc_dma_cmd(struct mmc_host *host, struct dma_config *cfg, struct mmc_command *cmd);
int msdc_dma_config(struct mmc_host *host, struct dma_config *cfg);
void msdc_dma_resume(struct mmc_host *host);
void msdc_dma_start(struct mmc_host *host);
void msdc_dma_stop(struct mmc_host *host);
int msdc_dma_wait_done(struct mmc_host *host, u32 timeout);

#if defined(FEATURE_MMC_SDIO)
int msdc_dma_iorw(struct mmc_card *card, int write, unsigned fn,
                  unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
#endif

//int msdc_dma_transfer(struct mmc_host *host, struct mmc_command *cmd, uchar *buf, ulong nblks);
int msdc_dma_transfer(struct mmc_host *host, struct mmc_command *cmd, struct mmc_data *data);
int msdc_dma_bread(struct mmc_host *host, uchar *dst, ulong src, ulong nblks);
int msdc_dma_bwrite(struct mmc_host *host, ulong dst, uchar *src, ulong nblks);

#endif //ifndef _MSDC_DMA_H_